package com.demo.dune.service.strategy;

import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import com.demo.dune.base.ServiceErrorException;
import com.demo.dune.domain.MemCreateInput;
import lombok.extern.slf4j.Slf4j;

/**
 * MemberStrategyContext, memberType and Strategy are one to one relationships.
 * @author Allen
 * @version 1.0 2022-04-03
 */
@Slf4j
@Component
public class MemberStrategyContext {
	
    private final Map<String, IMemberStrategy> strategyMap = new ConcurrentHashMap<String, IMemberStrategy>();

    /**
     * add Strategy to MemberStrategyContext.
     * @param memberStrategyList
     */
    public MemberStrategyContext(List<IMemberStrategy> memberStrategyList) {
        for (IMemberStrategy memberStrategy : memberStrategyList) {
            strategyMap.put(memberStrategy.getName(), memberStrategy);
            log.info("MemberStrategyContext add Strategy, name = {}", memberStrategy.getName());
        }
    } 
        
    /**
     * create Member.
     * @param memberInput
     * @throws ServiceErrorException
     */
    @Transactional
	public void createMem(MemCreateInput memberInput) throws ServiceErrorException {
    	if (memberInput == null) {
			log.error("createMem error, memberInput is null");
			throw new ServiceErrorException("service error");
    	}
    	String strategyName = MemberStrategyConst.getStrategyNameByMemType(memberInput.getType());
		log.info("strategyName={}", strategyName);
		if (StringUtils.isEmpty(strategyName)) {
			log.error("createMem error, strategyName is empty");
			throw new ServiceErrorException("service error");
		}
		IMemberStrategy strategy = this.strategyMap.get(strategyName);
    	if (strategy == null) {
			log.error("create error, strategy[{}] is null , not config", strategyName);
			throw new ServiceErrorException("service error");    		
    	}
		strategy.createMem(memberInput);
	}

    /**
     * calculate member's point.
     * @param strategyName
     * @param originalPrice
     * @return long
     * @throws ServiceErrorException
     */
    public long calcPoint(String strategyName, long originalPrice) throws ServiceErrorException {
		log.info("strategyName={}", strategyName);
		if (StringUtils.isEmpty(strategyName)) {
			log.error("calcPoint error, strategyName is empty");
			throw new ServiceErrorException("service error");
		}
    	IMemberStrategy strategy = this.strategyMap.get(strategyName);
    	if (strategy == null) {
			log.error("calcPoint error, strategy[{}] is null , not config", strategyName);
			throw new ServiceErrorException("service error");    		
    	}
        return strategy.calcPoint(originalPrice);
    }

}
